The file “CODE editor for ResEdit 2.1” contains a ResEdit 2.1 (or later) RSSC resource that adds a disassembly viewer to ResEdit to handle CODE and code-like resources. This allows you to view code resources as assembly code instead of “raw” hex. When added to ResEdit version 2.1.1 or later, the CODE editor can also operate concurrently with the basic HEXA editor, providing editing and searching capabilities as well. The disassembly code is annotated with the module names extracted from the MacsBug strings in the code. Navigation facilities are provided to allow viewing related pieces of code. And special formatting may be applied to the disassembly for embedded data that cannot normally be distinguished from actual code.
A typical CODE editor window has the following appearance:
If a ResEdit picker does not have a specific editor to handle a resource, it opens @HEXA as the default. This is a basic character/hex editor that allows you to find and change a resource as characters or in hex. The @CODE editor, because of the way it is named, overrides the default editor for resources of type 'CODE'. In addition, ResEdit RMAP resources are supplied to change the default to use the CODE editor for the following code-type resources:
I won't pretend to understand what all these are! If you have other code-type resources you can easily add RMAP's for them. More about this later in the section entitled “Adding New Code-like Resources”.
Resource types CODE and scod are handled fully. The CODE editor knows how to handle JUMP Table segment 0 and segment loader headers for both 16-bit and 32-bit segments. Other code resources are are treated as “pure” code.
When the CODE editor is opened, additional menus are added to the menu bar. This section describes those menus, changes to some of the standard ResEdit menus, and how you use the CODE editor. The menus are presented in a logical order to aid in describing the CODE editor and not the order they appear in the menu bar.
The Marker menu is alternate way from the mouse of manipulating the “marker”. The marker is the small pair of diamonds shown in the window around a resource address. The marker results from clicking an active address in the operand or comment field. An address or comment is indicated as active by showing a light-lined box around the address or comment pointed at by the mouse, and an arrow, in the left margin, extending from the line pointed to by mouse, to the line containing the address referenced. Off-window arrows (and references) extend to the top or bottom of the window in the appropriate direction. The target module offset and resource address are also enclosed in rectangles. See the window pictured above for an example.
You may treat the light-lined box as a button. Clicking it will let you “go to” the specified destination address. The destination address is indicated when you “get there” by the marker.
The marker itself is also a button. By clicking either one, you can go back to (display in the window) the line you most recently clicked that got you there. In this case the process is reversed and original “go-to” line gets the marker. At this point you could click the markers to “ping-pong” back and forth!
The Marker menu duplicates the mouse operations. They would generally be used when the marker has been scrolled out of the window. “Go to marker” moves the display to show the marker. “Go back” is the same as clicking the marker. “Clear marker” is special, in that is makes the marker “invisible”. Clicking it (if you can find it) will make it visible again.
The modules menu lists the names of all the modules found in the resource. By selecting a module name in the Modules menu, you change the window display to show that module.
The names are determined by the MacsBug symbols usually placed at the end of each module by the language compilers (e.g., MPW C and Pascal). If the CODE editor detects what it thinks is the end of a module, but cannot find a MacsBug symbol, the name “anonN” is used (which stands for “anonymous”), where N is a unique integer number.
For segments of type CODE or scod, some additional special names are placed in the Modules menu. They have the following meaning:
Seg loader info
The segment header “module” at the start of CODE or scod segment.
A5-rel Reloc Info
“Module” containing the 32-bit A5-relocation information.
Seg-rel Reloc Info
“Module” containing the 32-bit segment relative relocation information.
Unknown data
This usually results when data is encountered at the end of a code segment.
No name
Special name used internally. If you see this the CODE editor is “confused”!
The last two Modules menu entries are special cases. “Unknown data” usually results from C data declaration initializations. The more generic “Unknown data” is used because the CODE editor is not really sure! All it knows is that what it has detected as the last module of the code segment is NOT at the end of that segment. Stuff follows it to the end of the resource. That stuff is the “Unknown data”.
The “No name” case is the name the CODE editor gives a module before it knows where the module ends. If the resource is sufficiently confusing (it's not clear how) you could see this name. You probably shouldn't!
It should be pointed out here that the CODE editor is most reliable in detecting module boundaries when MacsBug symbols AND ALL THE RULES THAT GO WITH THEM are present in the code segment. The CODE editor looks for an RTS, RTD, or JMP (A0) as the end-of-module instruction. Following that there should be a MacsBug symbol and a constant data area size word (possibly with the value 0) immediately following the MacsBug symbol. That size tells the CODE editor how much to skip to the start of the next module and to more appropriately display the constants.
One final point about modules; as illustrated in the window pictured above, the small panel to the left of the horizontal scroll bar shows the module name of the module containing the top line in the window. As the window is scrolled, the module name in the panel will change appropriately. The panel may be clicked like a button. It has the same effect as selecting that module name from the Modules menu. This is convenient for quickly moving to the top of a module.
The Resource menu is the standard menu supplied by ResEdit. If you have added the CODE editor to ResEdit version 2.1.1 or later, the “Open Using Hex Edit” item is enabled. By selecting that item, you can open the standard @HEXA character/hex editor window AT THE SAME TIME the CODE editor window is open! The two editors can operate on the same resources concurrently. “Concurrently” in this case means that both operate on the same resource, but only one at a time -- whichever one is active.
Only one of the windows, CODE editor or HEXA editor is active at any one time. You click the window as usual to activate it. The two editors are distinct, but can communicate with each other. The CODE editor can tell what the HEXA editor's selection is and vice versa. The selection of the inactive editor is NOT updated until you make it active. On the other hand, if you revert the resource, the inactive editor's display is updated immediately.
No more will be said at this point regarding editing of the resource. It is discussed in more detail later. All I will say here is that you CAN edit the resource in the HEXA editor. The changes will be known to the CODE editor when you reactivate it. Indeed all the facilities (and warts) in the HEXA editor are available. So finds to change the selection will be reflected in the CODE editor when it is reactivated.
The Hex Editor menu tells the CODE editor some preference items on how to interact with the HEXA editor. Except for the last item, these are indeed preferences, and are remembered (along with the CODE editor's window position and size) in the standard ResEdit Preferences file.
In using the HEXA editor with the CODE editor, there are a number of alternative ways you can interact with it. You can open the HEXA editor “manually” using the Resource menu's “Open Using Hex Editor” item described above. Alternatively, you may elect to have the CODE editor open the HEXA editor for you at the time you open the CODE editor. The choice is made with the “Always open” and ”Open from menu” Hex Editor menu items.
“Always open” will do the “auto-open” of the HEXA editor at the time the CODE editor is opened. If the HEXA editor is not currently open, it will be opened just as if the “Open Using Hex Edit” was selected from the Resource menu. If it is already opened, it will be made the active window. Note, selecting “Open Using Hex Edit” will also make the HEXA editor active if it is already up. This functionality is the same as using ResEdit's Window menu.
If you choose “Open from menu”, then the HEXA editor must be manually opened using the “Open Using Hex Edit” Resource menu item.
Once the HEXA editor is opened, you have two choices on how to handle the synchronization of selections between the two editors. A “selection” in the CODE editor refers to a range of the hex bytes displayed at the right of each disassembly line. This is illustrated in the window pictured earlier. In that picture the selection is the inverted bytes at the right.
By choosing “Keep in sync.”, the CODE editor selection can be made to synchronize with the selection in the HEXA editor and vice versa. In that case whenever you switch from one editor to the other, the current selection will be made that of the other editor. The CODE editor will scroll the selection into view when reactivated whenever the selection has been changed.
Alternatively, you can choose “Don't keep in sync.”. In that case the CODE editor's selection is completely independent of the HEXA editor's selection.
Finally, you may have a selection in the CODE editor that has been scrolled off the screen. By choosing “Display selection” you can cause the window to scroll to it. Unlike the other items, this makes no sense to remember as a preference item.
The CODE editor knows the format of CODE and scod resources and it knows how to detect what it thinks is the end of a module. And that's about it! It does not know about special headers. Nor does it know about embedded data. These will “confuse” the disassembly display. They are treated like code and will usually produce some “valid” MC68XXX instruction according to the bits seen. Even CODE segments generated by most compilers produce areas of embedded data. The classic example is a word offset table for C switch and Pascal CASE statements. The Edit menu tries to address this problem by allowing you to “manually” format sections of the disassembly display.
The “Format as...” items in the Edit menu take the current selection (selections are discussed in the next section) and reformats it according to the item selected. There are certain rules and restrictions associated with this reformatting as follows:
(1). What can be formatted.
Formatting may only be applied to code or an entire “Unknown data” module. It cannot be applied to a Jump Table or to a CODE modules's segment header, or anything from the MacsBug symbol to the module that follows it (i.e., the stuff at the end of a module). The intent is to allow you to reformat only code (for those who care, the implementation is much more complex without these restriction).
(2). Which “Format as...” items can be applied.
“Format as...” items which cannot be applied are disabled (grayed out). However, items that are not disabled are NOT guaranteed to be allowed either! What an enabled item indicates is that the formatting MAY be possible for that item according to the rules we will discuss shortly. Until the actual formatting is attempted, the CODE editor does not know the selection is legal according to rule (1). Reformatting requires full reanalysis of the resource. That is when rule (1) is applied. The cost for this is unacceptable for a large resource just to enable and disable menu items.
The “Format as...” items are enabled as a function of alignment and what is selected. Thus “Format as Code” and “Format as Words” are allowed for selections which start on a word boundary are contain an even number of bytes. “Format as Longs” must start on a word boundary and contain a multiple of four bytes. “Format as Bytes...” has no such restrictions, and will always be enabled unless the current selection is just an insert point. For an insert point, only the “Format as End of line (CR)” (disabled in the above picture) will be enabled. The formats for all these items is discussed next.
(3). How the disassembly is reformatted by the “Format as...” items.
“Format as Code”: This is generally the original format for the selection. You would use this to reverse the effects of another formatting item applied to the selection. You could also use this to reformat a “Unknown data” module as code. According to rule (1) above, it's all or nothing for an “Unknown data” module. But you can fool the CODE editor by first formatting the module as code. It will cease to be “Unknown data” (it will become an unnamed module -- “AnonN”). After that you can use the other items as appropriate.
“Format as Bytes (1/line)”: Each byte in the selection is reformatted as “DC.B $XX”.
“Format as Bytes (up to 8/line)”: This is similar to “Format as Bytes (1/line)”, but with 8 bytes per disassembly line instead of 1. If there are less than 8 bytes in the selection, or it is not a multiple of 8, the only or last line will show the remaining bytes.
“Format as Words”: Each pair of bytes in the selection is reformatted as “DC.B $XXXX”.
“Format as Longs”: Each four bytes in the selection is reformatted as “DC.B $XXXXXXXX”.
“Format as End of line (CR)”: This is a special formatting case that is allowed only when the selection is an insert point. Functionally it is equivalent to selecting all the hex bytes on the line to the left of the insertion point and doing a “Format as Bytes (up to 8/line)”. This places those bytes on a separate line. The effect is to place a Return at the insertion point. A shorthand for the menu item (other than the Command-R key) is to simply press the Return key. The “(CR)” in the menu item is a reminder that you can do this. You can easily split up a sequence of bytes this way to reformat them on separate lines.
(4). What happens to the bytes on the line before and after the selection.
Formatting is applied to what was originally considered as “legal” code by the CODE editor. A selection that doesn't completely select all the bytes for an instruction is effectively producing an invalid instruction on the unselected bytes of that instruction line. This can happen at the start and/or end of the selection. In these cases the bytes before and after the selection could be formatted as “Format as Bytes (up to 8/line)”.
Up to three reformats can happen as a result of a single reformat operation. The stuff on the line before the selection. The selection itself. And the stuff on the line following the end of the selection. Of course, if the selection starts on an instruction boundary there is nothing to its left. Similarly, if the selection ends with the last byte of an instruction there is nothing to the right. But if the selection ends before that last instruction byte, the stuff to the right is only reformatted if the selection ends on a odd byte boundary. If it ends on an word boundary it is NOT reformatted.
The reasoning behind the treatment of the end of the selection is to allow you to separate data from “real” code that follows it. The code is always assumed to start on word boundaries. The data in front of an instruction could have been disassembled so that the real instruction got “sucked up” by a data word in front that was originally treated as an instruction. By reformatting the data, the actual instruction becomes visible. This is where the Return comes in handy to “Format as End of line (CR)”. Put the insert point at the end of the data and just hit Return!
Those are the rules. You really don't have to memorize them. Just try a reformat and see what happens. If it's wrong, you can always “Undo...”. As shown in the Edit menu picture above. If you want a copy of the selection you can use the “Copy” menu item. All the lines, from the line containing the start of the selection, to the line containing the end of the selection are copied as TEXT to the Clipboard. A module name in front of a selection is copied when the first byte of a module is selected.
If you decide you no longer want to see the reformatting you can choose the “Remove all added formatting” menu item. All the reformatting information accumulated up to that point is thrown away, and the display reverts to its original format. Note, that all the reformatting information is also thrown away when you close the window. It is NOT saved!
Use this reformatting sparingly! For one thing, you will not be able to save it as I just said. For another, each reformat is treated as pseudo edit operation, and as such, initiates a full reanalysis of the resource. Modules and their boundaries may have changed. Further, the formatting information must be scanned for each line of the disassembly. The more formatting you do, the more scanning that must be applied. All of this can be a time consuming processes on large modules when using lower performance machines! I do not recommend you use the CODE editor on such machines. Consider yourself warned.
No editing can be performed in the CODE editor other than the reformatting described above. “Editor” has been used rather loosely up to this point since it is the term, like “picker”, that ResEdit uses for such things. More precisely, the CODE editor is actually a viewer. The actual editing is done only from the HEXA editor. Refer to the appropriate ResEdit documentation for further details on how to use the HEXA editor.
What the CODE editor provides to the HEXA editor is basically another way of viewing the bytes. As such, only the hex bytes in the CODE editor may be selected in much the same manner as done in the HEXA editor and the HEXA editor can use that selection.
In the CODE editor, selections are made in the usual way. The basic arrow key selection operations, in combination with command and shift keys, are supported. Option-arrow keys are used only for scrolling. The extended keyboard home, end, page up, and page down keys are also supported. None of these keys are supported in the HEXA editor!
When editing is done in the HEXA editor, the changes are made in the CODE editor window when that window is reactivated. At this point the CODE editor must completely reanalyze the resource to see what's happened. As stated earlier for the reformatting Edit menu operations, this can can be a time consuming processes on large modules when using lower performance machines! Consider yourself warned...again!
The CODE editor is only compatible with ResEdit versions 2.1 or later. The protocols for ResEdit editors earlier than 2.1 are different and will NOT work with this editor. The CODE editor is supplied in the file “CODE editor for ResEdit 2.1”.
If you install the CODE editor into version 2.1.1 or later, you will be able to open the HEXA editor from the CODE editor to search or make changes to the resource. You will not be able to open the HEXA editor from the CODE editor in version 2.1.
“CODE editor for ResEdit 2.1” contains the CODE editor and all its associated resources. Using ResEdit, copy ALL the resources in “CODE editor for ResEdit 2.1” into ANOTHER copy of ResEdit. ResEdit is a program with many large resources so window updates may be relatively slow. Have patience!
It's very easy to make the CODE editor the default editor for new code-like resources. ResEdit supports a special RMAP resource to tell ResEdit which editor to use for a particular resource. It maps that resource on to the designated editor. The RMAP's are added to ResEdit as you would add any other resource. There are already examples in ResEdit to use as a guide. ResEdit provides a TMPL to make editing easy. The ones for the CODE editor are all numbered from 25000.
This section lists some possible future enhancements for the CODE editor. Some of these are more basic than others. The reason that some of these haven't been done is TIME. There isn't any! This editor was started as a simple one-week project to be done over Apple's Christmas break. The original intent was a simple disassembly viewer. Like most code projects, things got out of hand! But enough is enough. I am making no promises that any of these enhancements will be done. Or if there done, when. So here they are (in no particular order):
1. Printing. The ability to select a range and print the disassembly code for that range. The printing that is supported just displays the window.
2. More intelligent reanalysis. As discussed in the sections on formatting and editing, if you make any changes to the resource in the HEXA editor, or do any reformatting, the entire resource is reanalyzed. This can be slow for a larger resource on slower machines. It works. It's just slow. One thing that could be done is to only analyze from the point of the change or reformat. This still could be slow when editing the “top” of a resource.
You may question what this “reanalysis” is all about. The way the CODE editor handles the disassembly and the Modules menu is to essentially pre-paginate the entire display. It knows where lines begin as a function of resource offsets down to a resolution of about 50 lines. It does this by actually rehearsing the entire display. It would be great if we could keep this display. But the space requirements would be potentially enormous. Also, I did not want to use some sort of auxiliary disk file. That too would potentially require a lot of disk space. So the only space required is that for data structures and a buffer containing only the lines shown in the window. As you scroll around, the new lines in the window are being generated “on the fly”.
When you edit or reformat the resource, the entire “repagination” must be redone. It's relatively fast. But not that fast. Any improvement here would make editing more acceptable on slower machines. Fortunately, most code resources are not that big. On a Mac IIfx none of this seems to be a problem! But I don't recommend editing this way on a Mac SE or Classic!
3. A template mechanism to describe the layout of special code resources. Some code resources have special formats. For example, cdev's have a header block. Even a CODE resource has a segment loader header. The CODE editor knows about these. It's built-in. But it would be nice if there were some way to generalize this concept to be able to tell the CODE editor about special formats for other code-like resources like DA's. This would reduce, but not eliminate, the need for the formatting menu options.
4. Built-in editor as part of the CODE editor. All the selection mechanisms are in place in support of the HEXA editor. The reason the HEXA editor is used at all is, given the time constraints, there was too much “bang for the buck” to pass it up. There it was. Off the shelf, so to speak. Very little had to be done to it. Indeed, very little could be done to it since it is the default editor used by the rest of ResEdit.
Putting in a built-in editor is not as simple as it might appear (and no, I don't use TextEdit). It is not clear at this time what the paradigm should be. Currently the editing is modal. You switch to the HEXA editor. Make the changes. And then switch back to the CODE editor where the display is updated. If there is a built-in editor, when is the display updated? What happens if you edit more bytes than is shown for the line you are editing? You get the idea!
That's all the enhancements I can think of right now. I'm sure when you start using this thing you will think of a lot more. Then again, maybe not.
Oh, one more point. NO, I AM NOT GOING TO PUT AN ASSEMBLER IN! So don't even ask! Although, now that I think of it, it would solve the editing paradigm problem (more-or-less)!